/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQml.Models 2.12
import QtGraphicalEffects 1.0

import org.ukui.notification.core 1.0

import org.ukui.quick.items 1.0 as UkuiItems
import org.ukui.quick.platform 1.0 as Platform

Item {
    id: root
    height: childrenRect.height
    property int duration: 300
    property var groupData: null
    property int groupIndex: -1
    property alias listState: notificationListContent.state

    Component.onCompleted: {
        notificationModel.model = groupModel;
        notificationModel.rootIndex = notificationModel.modelIndex(root.groupIndex);
        notificationList.model = notificationModel;
    }

    DelegateModel {
        id: notificationModel
        property string name: groupData.groupName

        delegate: Item {
            id: delegateItem
            height: childrenRect.height
            width: notificationList.width
            property bool animationEnable: false
            property bool removeToClose: false
            state: "add"

            transform: Scale {
                yScale: notificationList.isCollapsed ?
                            ((collapsedLayout.firstItemHeight / height < 1) ? collapsedLayout.firstItemHeight / height : 1) : 1
            }

            Component.onCompleted: {
                z = notificationList.count - index;
                if (notificationList.isCollapsed) {
                    delegateContent.background.alpha = ((index === 0 && (notificationList.count > 1)) ? 1 : 0.85);

                    if (notificationList.itemLayout.length === 0) {
                        return;
                    }
                    if (isLiteMode) {
                        return;
                    }
                    y = notificationList.itemLayout[index];
                    if (y < screenMonitor.geometry.height) {
                        animationEnable = true;
                    }
                } else {
                    delegateContent.background.alpha = 0.85;
                    if (isLiteMode) {
                        return;
                    }
                    if (index > 3) {
                        opacity = 0;
                        scale = 0.85;
                    } else {
                        opacity = 1 - 0.05 * index;
                        scale = 1 - 0.05 * index;
                    }
                }
            }

            Behavior on y {
                enabled: animationEnable && !isLiteMode
                SequentialAnimation {
                    NumberAnimation { easing.type: Easing.InOutQuint; duration: 300 }
                    ScriptAction {
                        script: {
                            notificationList.isBusy = false;
                            animationEnable = false;
                            opacity = 0;
                        }
                    }
                }
            }
            Behavior on opacity {
                enabled: animationEnable
                NumberAnimation { easing.type: Easing.InOutQuint; duration: 300 }
            }
            Behavior on scale {
                enabled: animationEnable
                NumberAnimation { easing.type: Easing.InOutQuint; duration: 300 }
            }

            states: [
                State {
                    name: "normal"
                    PropertyChanges {
                        target: delegateContent
                        x: 0
                    }
                },
                State {
                    name: "add"
                    PropertyChanges {
                        target: delegateContent
                        x: notificationList.width
                    }
                },
                State {
                    name: "remove"
                    PropertyChanges {
                        target: delegateContent
                        x: -notificationList.width
                    }
                },
                State {
                    name: "forDeletion"
                    PropertyChanges {
                        target: delegateContent
                        x: -(removeButton.width + 8)
                    }
                    PropertyChanges {
                        target: removeButtonItem
                        visible: true
                    }
                }
            ]
            transitions: [
                Transition {
                    to: "normal"
                    enabled: !notificationList.isBusy && !isLiteMode
                    SequentialAnimation {
                        ScriptAction { script: notificationList.addFinished = false }
                        NumberAnimation { properties: "x"; easing.type: Easing.Bezier; easing.bezierCurve: [0.12,0,0.18,1,1,1]; duration: 300 }
                        ScriptAction { script: {
                                delegateItem.toNormalScript();
                            }
                        }
                    }
                },
                Transition {
                    to: "remove"
                    enabled: !isLiteMode
                    SequentialAnimation {
                        NumberAnimation { properties: "x"; easing.type: Easing.Bezier; easing.bezierCurve: [0.42,0,1,1,1,1]; duration: 200}
                        ScriptAction { script: {
                                delegateItem.toRemoveScript();
                            }
                        }
                    }
                },
                Transition {
                    to: "forDeletion"
                    enabled: !notificationList.isBusy
                    NumberAnimation { properties: "x"; easing.type: Easing.Bezier; easing.bezierCurve: [0.12,0,0.18,1,1,1]; duration: 300}
                }
            ]


            onStateChanged: {
                if (isLiteMode) {
                    if (state === "remove") {
                        delegateItem.toRemoveScript();
                        return;
                    }
                    if (state === "normal") {
                        delegateItem.toNormalScript();
                        return;
                    }
                }
            }
            function toNormalScript() {
                notificationList.addFinished = true;
                removeButtonItem.visible = false;
            }

            function toRemoveScript() {
                if (delegateItem.removeToClose) {
                    sourceModel.closeNotification(model.id)
                } else {
                    // 结合model的execAction方法，非常驻通知执行action后删除
                    sourceModel.execAction(model.id, delegateContent.action);
                }
            }

            // *********[drag]**********
            DragHandler {
                property real taregtX: target.x
                target: delegateContent
                enabled: !notificationList.isCollapsed || notificationList.count === 1
                yAxis.enabled: false

                onTaregtXChanged: {
                    if (isNotificationCenter) {
                        if (delegateContent.x < -48) {
                            removeButtonItem.width = 40;
                        } else if (delegateContent.x < 0 ) {
                            removeButtonItem.visible = true;
                            removeButtonItem.width = -delegateContent.x - 8;
                        } else {
                            removeButtonItem.visible = false;
                        }
                    }
                }

                onActiveChanged: {
                    delegateItem.state = "";
                    if (!active) {
                        if (isNotificationCenter) {
                            if (delegateContent.x < -notificationList.width * 0.5) {
                                delegateItem.removeToClose = true;
                                delegateItem.state = "remove";
                            } else if (delegateContent.x < -notificationList.width * 0.25) {
                                delegateItem.state = "forDeletion";
                            } else {
                                delegateItem.state = "normal";
                            }
                        } else {
                            if (delegateContent.x < -notificationList.width * 0.5) {
                                delegateItem.removeToClose = true;
                                delegateItem.state = "remove";
                            } else {
                                delegateItem.state = "normal";
                            }
                        }
                    } else {
                        notificationList.dragIndex = index;
                    }
                }
            }

            Item {
                id: removeButtonItem
                height: delegateContent.height
                width: 40
                visible: false
                opacity: width / 40
                anchors.right: parent.right

                UkuiItems.StyleBackground {
                    id: removeButton
                    height: width
                    width: parent.width
                    radius: width /2
                    useStyleTransparency: false
                    alpha: removeButtonArea.containsPress ? 0.65 : removeButtonArea.containsMouse ? 1.0 : 0.85
                    anchors.verticalCenter: parent.verticalCenter

                    // 深色主题下反色
                    UkuiItems.Icon {
                        height: parent.width * 0.4
                        width: height
                        anchors.centerIn: parent
                        mode: UkuiItems.Icon.ForceHighlight
                        source: "window-close-symbolic"
                    }
                    MouseArea {
                        id: removeButtonArea
                        anchors.fill: parent
                        hoverEnabled: true
                        visible: removeButton.visible
                        onClicked: {
                            delegateItem.removeToClose = true;
                            delegateItem.state = "remove";
                        }
                    }
                }
            }

            PopupNotificationItem {
                id: delegateContent
                property string action: ""
                height: childrenRect.height
                width: notificationList.width
                background.radius: isNotificationCenter ? 24 : 12

                pcTips.text: qsTr("%1 more notifications").arg(notificationList.count - 1)
                pcTips.visible: !isNotificationCenter && notificationList.isCollapsed && notificationList.count > 1 && index === 0
                tabletTips.text: qsTr("%1 more notifications").arg(notificationList.count - 1)
                tabletTips.visible: isNotificationCenter && notificationList.isCollapsed && notificationList.count > 1 && index === 0

                onActionExecuted: function (action) {
                    delegateContent.action = action;
                    if (model.resident) {
                        sourceModel.execAction(model.id, action);
                    } else {
                        delegateItem.removeToClose = false;
                        delegateItem.state = "remove";
                    }
                }

                onNotificationClosed: {
                    delegateItem.removeToClose = true;
                    delegateItem.state = "remove";
                }

                onClicked: {
                    if (model.hasDefaultAction) {
                        if (model.resident) {
                            sourceModel.execAction(model.id, "");

                        } else {
                            delegateContent.action = "";
                            delegateItem.removeToClose = false;
                            delegateItem.state = "remove";
                        }
                    }
                }

                Component.onCompleted: {
                    delegateItem.state = "normal"
                }
            }
        }
    }

    Repeater {
        id: notificationList
        width: parent.width
        height: childrenRect.height

        property bool isBusy: false
        property bool addFinished: true
        property bool isCollapsed: true
        property bool isExpand: groupData.groupIsExpand
        property var itemLayout: []
        property int dragIndex: -1

        onCountChanged: {
            if (count > 0) {
                collapsedLayout.firstItemHeight = itemAt(0).height;
                // 添加删除时，拖拽项重置
                dragIndex = -1;
            }
        }

        onIsExpandChanged: {
            isCollapsed = !isExpand
        }

        onDragIndexChanged: {
            for (var i = 0; i < count; i ++) {
                if (i === dragIndex) {
                    continue;
                }
                itemAt(i).state = "normal";
            }
        }

        function layout() {
            if (isCollapsed) {
                notificationList.parent = collapsedLayout;
                for (var j = 0; j < count; j ++) {
                    if (j > 2) {
                        itemAt(j).y = 0;
                        itemAt(j).opacity = 0;
                        itemAt(j).scale = 1 - 0.05 * j;

                    } else {
                        if (itemAt(j).height > itemAt(0).height) {
                            itemAt(j).y = 12 * j;
                        } else {
                            if (j === 0) {
                                itemAt(j).y = 0;
                            } else if (j === 1) {
                                itemAt(j).y = itemAt(0).height + 6 - itemAt(j).height * 0.95;
                            } else if (j === 2) {
                                itemAt(j).y = itemAt(0).height + 12 - itemAt(j).height * 0.95 * 0.95;
                            }
                        }

                        itemAt(j).opacity = j === 0 ? 1 : (j === 1 ? 0.75 : (j === 2 ? 0.35 : 0));
                        itemAt(j).scale = j === 0 ? 1 : (j === 1 ? 0.95 : (j === 2 ? 0.95 * 0.95: 0));
                    }
                }
            } else {
                notificationList.parent = expandedLayout;
            }
        }

        Component.onCompleted: {
            notificationList.parent = collapsedLayout;
            if (isLiteMode) {
                return;
            }

            for (var j = 1; j < count; j ++) {
                itemAt(j).y = 0;
                itemAt(j).opacity = 0;
            }
        }

        onIsCollapsedChanged: {
            if (!isLiteMode) {
                isBusy = true;
                layout();
                collapsedLayout.firstItemHeight = itemAt(0).height;
            } else {
                if (isCollapsed) {
                    notificationList.parent = collapsedLayout;
                } else {
                    notificationList.parent = expandedLayout;
                }
            }
        }
    }
    // [folder mouseArea]
    MouseArea {
        width: notificationList.parent.width
        height: notificationList.parent.height
        enabled: notificationList.isCollapsed && (notificationList.count > 1)
        z: 10
        onClicked: {
            if (notificationListContent.state === "normal") {
                notificationModel.model.setData(notificationModel.rootIndex, true, NotificationItem.GroupIsExpand);
            }
        }

        drag.target: notificationListContent
        drag.axis: Drag.XAxis
        drag.onActiveChanged: {
            notificationListContent.state = ""
            if (!drag.active) {
                if (isNotificationCenter) {
                    if (notificationListContent.x < -notificationList.width * 0.5) {
                        notificationListContent.state = "remove";
                    } else if (notificationListContent.x < -notificationList.width * 0.25) {
                        notificationListContent.state = "forDeletion";
                    } else {
                        notificationListContent.state = "normal";
                    }
                } else {
                    if (notificationListContent.x < -notificationList.width * 0.5) {
                        notificationListContent.state = "remove";
                    } else {
                        notificationListContent.state = "normal";
                    }
                }
            } else {
                parent.ListView.view.dragIndex = root.groupIndex;
            }
        }
    }

    // [===notificationListContent===]
    Column {
        id: notificationListContent
        width: parent.width
        height: childrenRect.height
        state: "normal"

        // [header: folderButtton and clearButton]
        Item {
            id: functionButton
            width: parent.width

            state: (!notificationList.isCollapsed && notificationList.count > 1) ? "show" : "hide"
            states: [
                State {
                    name: "show"
                    PropertyChanges { target: functionButton; opacity: 1;
                        height: functionButton.visible ? (isNotificationCenter ? 48+8 : 36+8) : 0 }
                },
                State {
                    name: "hide"
                    PropertyChanges { target: functionButton; opacity: 0; height: 0 }
                }
            ]
            transitions: Transition {
                enabled: !isLiteMode
                NumberAnimation { easing.type: Easing.InOutCubic; properties: "opacity, height"; duration: 200 }
            }

            RowLayout {
                id: functionLayout
                width: parent.width
                height: isNotificationCenter ? 48 : 36

                anchors.topMargin: 8
                spacing: 8
                anchors.left: parent.left

                UkuiItems.StyleBackground {
                    id: foldbutton
                    Layout.maximumWidth: parent.width - parent.spacing - clearButton.width
                    Layout.preferredWidth: childrenRect.width
                    Layout.fillHeight: true

                    radius: isNotificationCenter ? (height / 2) : 6
                    paletteRole: Platform.Theme.Base

                    Row {
                        width: childrenRect.width + 16
                        height: parent.height
                        x: 16
                        clip: true
                        spacing: 8

                        UkuiItems.Icon {
                            id: showLessIcon
                            anchors.verticalCenter: parent.verticalCenter

                            height: 20
                            width: height
                            source: "ukui-up-symbolic"
                            mode: UkuiItems.Icon.AutoHighlight
                        }

                        UkuiItems.StyleText {
                            id: showLessText
                            anchors.verticalCenter: parent.verticalCenter

                            onContentWidthChanged: {
                                // TODO: 禁止文字超长
                                width = contentWidth
                            }
                            text: qsTr("Show less")
                            elide: Text.ElideRight
                        }
                    }

                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            notificationModel.model.setData(notificationModel.rootIndex, false, NotificationItem.GroupIsExpand);
                        }
                    }
                }

                Item {
                    id: clearButton
                    Layout.fillHeight: true
                    Layout.preferredWidth: height
                    Layout.maximumWidth: height
                    Layout.minimumWidth: height
                    Layout.alignment: Qt.AlignVCenter | Qt.AlignRight

                    //平板模式下清空按钮
                    UkuiItems.Button {
                        id: clear
                        anchors.centerIn: parent
                        height: parent.height
                        width: height

                        background.radius: height / 2
                        background.useStyleTransparency: false
                        background.paletteRole: Platform.Theme.Base
                        background.alpha: containsPress ? 1 : containsMouse ? 0.80 : 0

                        icon.source: "window-close-symbolic"
                        icon.mode: UkuiItems.Icon.AutoHighlight
                        visible: isNotificationCenter

                        onClicked: {
                            notificationListContent.state = "removeFromY"
                        }
                    }

                    //pc侧边栏清空按钮
                    UkuiItems.Button {
                        anchors.centerIn: parent
                        height: parent.height
                        width: height

                        background.radius: height / 2
                        background.useStyleTransparency: false
                        background.paletteRole: Platform.Theme.Button
                        background.alpha: containsPress ? 1 : containsMouse ? 0.80 : 0

                        icon.source: "window-close-symbolic"
                        icon.mode: UkuiItems.Icon.AutoHighlight
                        visible: !isNotificationCenter

                        onClicked: {
                            notificationListContent.state = "removeFromY"
                        }
                    }
                }
            }
        }

        // [content: notification]
        Column {
            id: expandedLayout
            width: parent.width
            height: childrenRect.height
            spacing: 8

            add: Transition {
                enabled: !isLiteMode
                SequentialAnimation {
                    ParallelAnimation {
                        NumberAnimation { easing.type: Easing.InOutQuad; properties: "y"; duration: 300 }
                        NumberAnimation { properties: "scale, opacity"; to: 1; duration: 300 }
                    }
                    ScriptAction {
                        script: {
                            notificationList.itemLayout = [];
                            for (var i = 0; i < notificationList.count; i++) {
                                notificationList.itemLayout.push(notificationList.itemAt(i).y);
                            }
                            notificationList.isBusy = false;
                        }
                    }
                }
            }
            move: Transition {
                enabled: !notificationList.isCollapsed && !isLiteMode
                NumberAnimation { easing.type: Easing.InOutQuad; properties: "y"; duration: 300 }
            }
        }
        Item {
            id: collapsedLayout
            width: parent.width
            height: notificationList.isBusy ? childrenRect.height : (children.length === 0 ? 0 : firstItemHeight)
            property int firstItemHeight
        }

        // [footer: folderBar]
        Column {
            id: foldingBar
            height: (notificationList.count > 1) ? childrenRect.height : 0
            width: parent.width
            visible: notificationList.isCollapsed && !notificationList.isBusy && notificationList.addFinished
            property int radius: isNotificationCenter ? 24 : 12
            property int barHeight: 8

            Item {
                width: notificationList.width
                height: notificationList.count > 1 ? foldingBar.barHeight : 0
                clip: true
                scale: 0.95

                UkuiItems.StyleBackground {
                    useStyleTransparency: false
                    paletteRole: Platform.Theme.Base
                    alpha: 0.75
                    radius: foldingBar.radius
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.bottom: parent.bottom
                    width: parent.width
                    height: radius * 2
                }
            }
            Item {
                width: notificationList.width
                height: notificationList.count > 2 ? foldingBar.barHeight : 0
                clip: true
                scale: 0.95 * 0.95

                UkuiItems.StyleBackground {
                    useStyleTransparency: false
                    paletteRole: Platform.Theme.Base
                    alpha: 0.35
                    radius: foldingBar.radius
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.bottom: parent.bottom
                    width: parent.width
                    height: radius * 2
                }
            }
        }

        states: [
            State {
                name: "normal"
                PropertyChanges {
                    target: notificationListContent
                    x: 0
                }
            },
            State {
                name: "forDeletion"
                PropertyChanges {
                    target: notificationListContent
                    x: -(removeButtonGroups.width + 8)
                }
            },
            State {
                name: "remove"
                PropertyChanges {
                    target: notificationListContent
                    x: -notificationList.width
                }
            },
            State {
                name: "removeFromY"
                PropertyChanges {
                    target: notificationListContent
                    y: -notificationListContent.height
                    opacity: 0
                }
                PropertyChanges {
                    target: root
                    height: 0
                    clip: true
                }
            }
        ]

        onStateChanged: {
            if (isLiteMode) {
                if (state === "remove" || state === "removeFromY") {
                    groupModel.clearGroup(notificationModel.rootIndex);
                }
            }
        }
        transitions: [
            Transition {
                to: "normal, forDeletion"
                enabled: !isLiteMode
                NumberAnimation { properties: "x"; easing.type: Easing.Bezier; easing.bezierCurve: [0.12,0,0.18,1,1,1]; duration: 300 }
            },
            Transition {
                to: "remove, removeFromY"
                enabled: !isLiteMode
                SequentialAnimation {
                    NumberAnimation { properties: "x, y, height, opacity"; easing.type: Easing.Bezier; easing.bezierCurve: [0.42,0,1,1,1,1]; duration: 300}
                    ScriptAction { script: groupModel.clearGroup(notificationModel.rootIndex); }
                }
            }
        ]
    }

    Item {
        id: removeButtonGroups
        height: notificationListContent.height
        width: Math.min((-notificationListContent.x - 8), 40)
        visible: (notificationListContent.x < 0) && isNotificationCenter
        opacity: width / 40
        anchors.right: parent.right
        z: 20

        UkuiItems.StyleBackground {
            height: width
            width: parent.width
            radius: width /2
            useStyleTransparency: false
            alpha: buttonArea.containsPress ? 0.65 : buttonArea.containsMouse ? 1.0 : 0.85
            anchors.verticalCenter: parent.verticalCenter

            // 深色主题下反色
            UkuiItems.Icon {
                height: parent.width * 0.4
                width: height
                anchors.centerIn: parent
                mode: UkuiItems.Icon.ForceHighlight
                source: "window-close-symbolic"
            }
            MouseArea {
                id: buttonArea
                anchors.fill: parent
                hoverEnabled: true
                onClicked: {
                    notificationListContent.state = "remove";
                }
            }
        }
    }
}
